<template>
  <el-form
    ref="formRef"
    class="form_basic_wrap"
    :size="size"
    :rules="rules"
    :inline="inline"
    :disabled="disabled"
    :model="tempFormData"
    :label-width="labelWidth"
    :status-icon="statusIcon"
    :show-message="showMessage"
    :label-position="labelPosition"
    :inline-message="inlineMessage"
    :scroll-to-error="scrollToError"
    :hide-required-asterisk="hideRrequiredAsterisk"
  >
    <template v-for="(formItem, idx) in formItemPropsConfig" :key="idx">
      <!-- 下拉选表单元素 select -->
      <el-form-item
        :label="formItem.label"
        :prop="formItem.vModel"
        v-if="formItem.type === 'select'"
      >
        <el-select
          @change="formItem.onSelectChang;"
          v-model="tempFormData[formItem.vModel]"
          :placeholder="formItem.placeholder"
          clearable
          :filterable="formItem.filterable"
        >
          <el-option
            v-for="(selectItem, selectIdx) in formItem.selectList"
            :key="selectIdx"
            :label="selectItem.label"
            :value="selectItem.value"
          />
        </el-select>
      </el-form-item>
      <!-- 复选框表单元素 checkbox -->
      <el-form-item
        :label="formItem.label"
        :prop="formItem.vModel"
        v-else-if="formItem.type === 'checkbox'"
      >
        <el-checkbox-group
          v-model="tempFormData[formItem.vModel]"
          @change="formItem.onCheckboxChange"
        >
          <el-checkbox
            v-for="(checkboxItem, checkboxtIdx) in formItem.checkboxList"
            :key="checkboxtIdx"
            :label="checkboxItem"
            :name="formItem.checkboxName || `${idx}`"
          />
        </el-checkbox-group>
      </el-form-item>
      <!-- 开关按钮表单元素 switch -->
      <el-form-item
        :label="formItem.label"
        :prop="formItem.vModel"
        v-else-if="formItem.type === 'switch'"
      >
        <el-switch
          :width="formItem.width"
          @change="formItem.onSwicthChange"
          :active-text="formItem.activeText"
          :inactive-text="formItem.inActiveText"
          :inline-prompt="formItem.inlinePrompt"
          :active-value="formItem.activeValue"
          :inactive-value="formItem.inActiveValue"
          :style="{
            '--el-switch-on-color': formItem.activeColor,
            '--el-switch-off-color': formItem.inActiveColor,
          }"
          v-model="tempFormData[formItem.vModel]"
        />
      </el-form-item>
      <!-- 文本框表单元素 textarea -->
      <el-form-item
        :label="formItem.label"
        :prop="formItem.vModel"
        v-else-if="formItem.type === 'textarea'"
      >
        <el-input
          type="textarea"
          v-model="tempFormData[formItem.vModel]"
          :placeholder="formItem.placeholder"
        />
      </el-form-item>
      <!-- 单选按钮表单元素 radio -->
      <el-form-item
        :label="formItem.label"
        :prop="formItem.vModel"
        v-else-if="formItem.type === 'radio'"
      >
        <el-radio-group v-model="tempFormData[formItem.vModel]" @change="formItem.onRadioChange">
          <el-radio
            v-for="(radioItem, radiotIdx) in formItem.radioList"
            :key="radiotIdx"
            :label="radioItem"
          />
        </el-radio-group>
      </el-form-item>
      <!-- 时间表单元素 date -->
      <el-form-item
        :label="formItem.label"
        :prop="formItem.vModel"
        v-else-if="formItem.type === 'date'"
      >
        <el-date-picker
          v-model="tempFormData[formItem.vModel]"
          :placeholder="formItem.placeholder"
          :type="formItem.dateType"
          :format="formItem.format"
          :value-format="formItem.valueFormat"
        />
      </el-form-item>
      <!-- 默认普通表单元素 input -->
      <el-form-item :label="formItem.label" :prop="formItem.vModel" v-else>
        <el-input
          v-model="tempFormData[formItem.vModel]"
          :placeholder="formItem.placeholder"
          clearable
        />
      </el-form-item>
    </template>
    <el-form-item>
      <slot name="handle">
        <el-button v-if="btnSubmitIsShow" type="primary" @click="submit(formRef)">
          {{ btnSubmitMsg }}
        </el-button>
        <el-button v-if="btnResetIsShow" @click="resetForm(formRef)">
          {{ btnResetMsg }}
        </el-button>
      </slot>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { nextTick, ref, unref, watchEffect } from "vue";
import { FormInstance, FormRules } from "element-plus";
import type { FormItemPropsConfig } from "types/components/form";
// 注册分发事件
const emit = defineEmits(["onSubmit", "resetForm"]);
// 暴露事件
defineExpose({ submit, resetForm });
const formRef = ref<FormInstance>();
interface FormProps {
  /**
   * 是否显示表单提交按钮
   */
  btnSubmitIsShow?: boolean;
  /**
   * 表单提交按钮上的文字信息。例如：提交
   */
  // btnSubmitMsg?: string;
  btnSubmitMsg?: string;
  /**
   * 是否显示重置表单按钮
   */
  btnResetIsShow?: boolean;
  /**
   * 表单重置按钮上显示文字信息。例如：重置
   */
  btnResetMsg?: string;
  /**
   * 开启表单校验功能
   */
  rules?: FormRules;
  /**
   * 行内表单模式
   * true:行内表单，
   * false:非行内表单
   */
  inline?: boolean;
  /**
   * 表单数据对象
   */
  formItemPropsConfig: Array<FormItemPropsConfig>;
  /**
   * 标签对齐方式
   * 可选值："left" | "right" | "top"
   */
  labelPosition?: "left" | "right" | "top";
  /**
   * 标签的长度，例如 '50px'。
   * 作为 Form 直接子元素的 form-item 会继承该值。 可以使用 auto
   */
  labelWidth?: string | "auto";
  /**
   * 是否显示必填字段的标签旁边的红色星号，默认false
   */
  hideRrequiredAsterisk?: boolean;
  /**
   * 是否以行内形式展示校验信息，默认false
   */
  inlineMessage?: boolean;
  /**
   * 是否在输入框中显示校验结果反馈图标，默认为false
   */
  statusIcon?: boolean;
  /**
   * 是否显示校验错误信息，默认为true
   */
  showMessage?: boolean;
  /**
   * 用于控制该表单内组件的尺寸
   */
  size?: "large" | "default" | "small";
  /**
   * 是否禁用该表单内的所有组件。
   * 如果设置为 true, 它将覆盖内部组件的 disabled 属性
   * ，默认为false
   */
  disabled?: boolean;
  /**
   * 当校验失败时，滚动到第一个错误表单项，默认为false
   */
  scrollToError?: boolean;
  /**
   * 表单回显数据
   */
  echo?: Object;
}
// 表单管理数据的对象
const tempFormData = ref({});
const props = withDefaults(defineProps<FormProps>(), {
  inline: false,
  labelPosition: "right",
  showMessage: true,
  labelWidth: "120px",
  echo: () => ({}),
  btnResetIsShow: true,
  btnSubmitIsShow: true,
  btnResetMsg: "重置",
  btnSubmitMsg: "提交",
});
// 处理表单回显问题
watchEffect(() => {
  const keys = Object.keys(props.echo);
  if (keys.length) {
    nextTick(() => {
      props.formItemPropsConfig.forEach((item, index) => {
        keys.forEach((k) => {
          if (k === item.vModel) {
            tempFormData.value[k] = props.echo[k];
          }
        });
      });
    });
  }
});
/**
 * 重置表单
 */
function resetForm(formEl: FormInstance | undefined) {
  console.log("重置表单：", formEl);
  if (!formEl) return;
  formEl.resetFields();
}
/**
 * 提交表单信息
 * @param formEl 表单对象元素
 */
function submit(formEl: FormInstance | undefined) {
  console.log("submit 校验前：", tempFormData.value);
  if (formEl && props.rules) {
    formEl.validate((valid) => {
      if (valid) {
        emit("onSubmit", unref(tempFormData.value));
      } else {
        return false;
      }
    });
  } else {
    emit("onSubmit", unref(tempFormData.value));
  }
}
</script>
